package com.mi.utils;

import java.io.File;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.Enumeration;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.Part;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.log4j.Logger;

import com.mi.bean.SysdbapswBean;

public class MyUtils {

	/**
	 * log4j日志对象
	 */
	public static Logger logRootLogger = Logger.getLogger("rootLogger");

	
	/**
	 *删除管理员信息操作时将传输的数据转换为实体类，便于后续操作 
	 */


	public static <T> T mconvertData2Bean(HttpServletRequest request, Class<T> clazz) {
		// 创建一个指定类的实例对象
		T t = getInstance(clazz);
		// 获取传输过来的数据manager_name的值
		String strVal = request.getParameter("manager_count");
		try {
			//映射到实体类中，使用反射机制
			BeanUtils.setProperty(t, "manager_count", strVal);
		} 
		 catch (Exception e) {
			// form表单属性值映射到实体类异常
				logRootLogger.error("传输的数据映射到实体类异常" + e.getMessage());
				e.printStackTrace();
		}
		return t;
	}
	
	
	public static <T> T convertData2Bean(HttpServletRequest request, Class<T> clazz) {
		// 创建一个指定类的实例对象
		T t = getInstance(clazz);
		// 获取传输过来的数据manager_name的值
		String strVal = request.getParameter("customer_id");
		try {
			//映射到实体类中，使用反射机制
			BeanUtils.setProperty(t, "customer_id", strVal);
		} 
		 catch (Exception e) {
			// form表单属性值映射到实体类异常
				logRootLogger.error("传输的数据映射到实体类异常" + e.getMessage());
				e.printStackTrace();
		}
		return t;
	}
	
	
	
	/**
	 * 约定：form表单的那么属性值要与（对应实体类的属性名【数据库的字段名】）保持一致【大小写敏感】
	 * 使用反射将request提交的form表单数据映射到实体类中
	 * 
	 * @param request request请求对象
	 * @param clazz   实体类的Class类实例
	 * @return 映射表单数据的实体类实例
	 */
	public static <T> T convertFormData2Bean(HttpServletRequest request, Class<T> clazz) {
		// 创建一个指定类的实例对象
		T t = getInstance(clazz);

		// ========================form表单数据映射到实体类处理=========================== //

		// 注册自定义的转换器，将form表单中String类型的日期字符串转换成Date类型
		// 第一个参数是自定义转换器的一个实例，第二个参数是要转换的目标类型
		ConvertUtils.register(new DateTimeConverter(), Date.class);

		if (request != null) {

			// getParameterNames:获取request 中提交的所有form表单控件的name属性值
			// Enumeration是一个form表单name属性值的"集合"
			Enumeration<String> paramName = request.getParameterNames();
			if (paramName != null) {
				try {
					// 遍历每一个元素
					// hasMoreElements(),判断paramName中是否还有元素，返回boolean值
					while (paramName.hasMoreElements()) {
						// 取出当前遍历的name属性的值
						String strName = paramName.nextElement();
						// 获取该name属性所对应的表单控件所对应的输入的值
						String strVal = request.getParameter(strName);
						// 使用反射将表单的Value值设置到与之对应的实体类属性中【借助BeanUtils包】
						BeanUtils.setProperty(t, strName, strVal);
					}
				} catch (Exception e) {
					// form表单属性值映射到实体类异常
					logRootLogger.error("form表单属性值映射到实体类异常" + e.getMessage());
					e.printStackTrace();
				}
			}
		}
		// ========================form表单数据映射到实体类处理=========================== //

		// ========================文件映射到实体类处理=========================== //
		// form表单中的文件映射到实体类中，首先将上传的文件保存到服务器指定目录下，再将文件的存储路径存储到数据库中
		// 判断当前request请求中是否包含了流文件
		System.out.println("request中的上下文内容"+request.getContentType());
		if (request.getContentType()!=null && request.getContentType().split(";")[0].equals("multipart/form-data")) {
			try {
				// 获取request中的所有的控件的part集合【每个part中包含form表单中的一个控件对象】
				Collection<Part> parts = request.getParts();
				// 临时参数
				String uploadDerictory = "amdinImgs";
				// 定义一个文件名的前缀
				String uploadFilePrefix = "amdinImg";

				// 遍历每一个part，处理含有文件的part部分
				if (parts != null && parts.size() > 0) {
					for (Part part : parts) {
						// 检查含有文件流的part部分进行处理
						// 使用part的ContentType来区分该part是包含文件流控件还是普通控件
						// 获取 MINE类型，普通控件的该属性是 null，
						// 包含上传文件的控件，该属性不是null
						String partContent = part.getContentType();

						// part.getSize()返回的所上传文件的大小，确保有文件上传过来
						if (partContent != null && !partContent.equals("") && part.getSize() > 0) {
							// 此时获取到了包含上传文件的控件

							// 处理含有文件流空间的part，进行文件上传
							// 准备文件上传的服务器的路径地址【要求是绝对地址】【文件在服务器上的存储位置】
							System.out.println("ContextPath"+request.getContextPath());
							System.out.println("RealPath"+request.getServletContext().getRealPath("/"));
							String strRealPath = request.getServletContext().getRealPath("/");

							// 规定：默认存储在 static/goodsfiles/
							String strUploadPath = strRealPath;
							// 文件上传时保存的相对路径地址
							String strRelativePath = "static/goodsfiles/" + uploadDerictory;

							// 检测文件上传目录是否已经存在，如果不存在，则创建
							File file = new File(strUploadPath + strRelativePath);
							if (!file.exists()) {
								// 若该文件目录不存在，创建该目录
								file.mkdirs();
							}

							// 默认文件后缀为.dat
							String strFileType = ".dat";
							// 获取包含文件后缀信息的上下文的字符描述串
							String strContent = part.getHeader("Content-Disposition");
							// System.out.println("包含文件后缀信息的上下文的字符描述串" + strContent);
							// 正则表达式匹配文件后缀
							String strReg = "\\.\\w*";
							// 创建正则表达式类
							Pattern pattern = Pattern.compile(strReg);
							// 进行匹配操作
							Matcher matcher = pattern.matcher(strContent);
							if (matcher.find()) {
								strFileType = matcher.group(0);
							}  
							// 组合一个具有随机码的文件名，防止文件重名
							String strNewFileName = uploadFilePrefix + "_" + System.currentTimeMillis() + strFileType;

							// 使用反射将文件存储的相对路径保存到实例类的属性中
							// 上传文件对象
							// 绝对路径 + 相对路径 + / + 随机文件名，指明上传的文件输出到服务器的那个文件中
							part.write(strUploadPath + strRelativePath + File.separatorChar + strNewFileName);

							// 将文件的相对路径保存到文件的实体类属性中
							// 获取文件上传控件的name属性
							String strFieldName = part.getName();
							// 使用反射将表单的value值设置到与之对应的实体类属性中【借助beanutils或者直接使用反射】
							BeanUtils.setProperty(t, strFieldName,
									strRelativePath + File.separatorChar + strNewFileName);

						} else {
							// 处理普通控件
							// 如果在此处进行处理，需要aciton中添加@MultipartConfig注解，所以不建议在此处进行普通控件的处理
						}
					}
				}

			} catch (Exception e) {
				// 文件上传处理异常
				logRootLogger.info("文件上传处理异常：" + e.getMessage());
				e.printStackTrace();
			}
		}

		// ========================文件映射到实体类处理=========================== //
		System.out.println("管理员密码："+new SysdbapswBean().getDbapsw());
		return t;
	}

	/**
	 * 将Date类型的日期转换为String类型的日期【转换失败返回null】
	 * 
	 * @param date          被转换的Date类型的时间
	 * @param strDateFormat 时间格式字符串
	 * @return 转换后的String类型的日期
	 */
	public static String convertDate2String(Date date, String strDateFormat) {
		// 返回值
		String strDate = null;

		// 日期格式串检测
		if (strDateFormat == null || strDateFormat.equals("")) {
			// 给定默认的时间格式字符串
			strDateFormat = "yyyy-MM-dd hh:mm:ss";
		}

		// 创建一个SimpleDateFormat类
		SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
		// 将日期类型转换成指定格式的字符串
		if (date != null) {
			// 转换Date类型
			strDate = sdf.format(date);
		} else {
			// 将当前时间转换输出
			// strDate = sdf.format(new Date());
		}
		// 返回值
		return strDate;

	}

	/**
	 * 将Date型日期转换为String型日期 【注意：日期字符串与日期格式串要匹配】
	 * 
	 * @param strDate       要转换的 String型日期
	 * @param strDateFormat 自定义的转换格式字符串
	 * @return 返回转换后的Date型日期，默认为当前系统时间
	 */
	public static Date convertString2Date(String strDate, String strDateFormat) {
		// 返回值是Date类型，默认返回当前时间
		Date date = new Date();

		// 日期格式串检测【注意：日期字符串与日期格式串要匹配】
		if (strDateFormat == null || strDateFormat.equals("")) {
			// 若没有给定格式，则给出默认的时间格式字符串
			strDateFormat = "yyyy-MM-dd hh:mm:ss";
		}

		// 创建SimpleDateFormat，可以将Date转换为自定义的格式的String类型
		SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);

		try {
			// 进行日期转换
			date = sdf.parse(strDate);
		} catch (ParseException e) {
			// 日期转换异常
			logRootLogger.info("Date日期转换为String类型转换异常：" + e.getMessage());
			e.printStackTrace();
		}
		// 返回值
		return date;
	}

	/**
	 * 简单工厂模式：获取一个指定Class的实例对象
	 * 
	 * @param clazz class
	 * @return 实例对象
	 */
	public static <T> T getInstance(Class<T> clazz) {
		T t = null;
		// 获取该Class类实例的一个实例对象
		try {
			t = clazz.newInstance();
		} catch (InstantiationException | IllegalAccessException e) {
			logRootLogger.info("获取实例对象异常！" + e.getMessage());
			e.printStackTrace();
		}
		return t;

	}
}
